home *** CD-ROM | disk | FTP | other *** search
/ Winzipper / Winzipper_ISO.iso / programming / oracle7 7.2 / OCI72 / CDEMO4.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-19  |  11.3 KB  |  413 lines

  1. #ifdef RCSID
  2. static char *RCSid = 
  3.    "$Header: cdemo4.c 7020100.1 94/09/23 22:19:27 cli Generic<base> $ ";
  4. #endif /* RCSID */
  5.  
  6. /* Copyright (c) 1991 by Oracle Corporation */
  7. /*
  8.    NAME
  9.      cdemo4.c - <one-line expansion of the name>
  10.    DESCRIPTION
  11.      <short description of component this file declares/defines>
  12.    PUBLIC FUNCTION(S)
  13.      <list of external functions declared/defined - with one-line descriptions>
  14.    PRIVATE FUNCTION(S)
  15.      <list of static functions defined in .c file - with one-line descriptions>
  16.    RETURNS
  17.      <function return values, for .c file with single function>
  18.    NOTES
  19.      <other useful comments, qualifications, etc.>
  20.    MODIFIED   (MM/DD/YY)
  21.     emendez    04/07/94 -  merge changes from branch 1.4.710.3
  22.     gdoherty   04/06/94 -  merge changes from branch 1.4.710.1
  23.     emendez    02/07/94 -  fix for bug 196094
  24.     emendez    02/02/94 -  Fix for bug 157576
  25.     gdoherty   02/02/94 -  make oci header inclusion for ansi or k+r adaptive
  26.     lfeng      01/13/93 -  fix non-portable fflush 
  27.     rkooi2     11/27/92 -  Changing e... datatypes to s... 
  28.     kaghevli   11/06/92 -  test 
  29.     rkooi2     10/29/92 -  Creation 
  30. */
  31. /* cdemo4.c
  32.  *
  33.  *  Demonstrates doing a FETCH from a cursor
  34.  *  into PL/SQL tables.  The tables are bound to C
  35.  *  arrays using the obndra routine.
  36.  *  The fully-commented script to create the stored procedure
  37.  *  is in the demo program file calldemo.sql.
  38.  *
  39.  *  Execute this script using SQL*DBA or SQL*Plus
  40.  *  to store the package before executing this program.
  41.  *
  42.  * The script is:
  43.  * create or replace package calldemo as
  44.  * 
  45.  *   type char_array is table of varchar2(20) index by binary_integer;
  46.  *   type num_array is table of float index by binary_integer;
  47.  * 
  48.  *   procedure get_employees(
  49.  *     dept_number in     integer,   -- which department to query
  50.  *     batch_size  in     integer,   -- how many rows at a time
  51.  *     found       in out integer,   -- n of rows actually returned
  52.  *     done_fetch  out    integer,   -- all done flag
  53.  *     emp_name    out    char_array,-- arrays of employee names,
  54.  *     job         out    char_array,--                    jobs,
  55.  *     sal         out    num_array);--                    salaries
  56.  * 
  57.  * end;
  58.  * /
  59.  * 
  60.  * create or replace package body calldemo as
  61.  * 
  62.  *   cursor get_emp(
  63.  *     dept_number in     integer) is
  64.  *       select ename, job, sal from emp
  65.  *       where deptno = dept_number;
  66.  * 
  67.  * -- Procedure get_employees fetches a batch of employee
  68.  * -- rows (batch size is determined by the client/caller
  69.  * -- of this procedure).  Procedure may be called from
  70.  * -- other stored procedures or client application
  71.  * -- programs.  The procedure opens the cursor if it is
  72.  * -- not already open, fetches a batch of rows, and
  73.  * -- returns the number of rows actually retrieved.  At
  74.  * -- end of fetch, the procedure closes the cursor.
  75.  * 
  76.  *   procedure get_employees(
  77.  *     dept_number in     integer,
  78.  *     batch_size  in     integer,
  79.  *     found       in out integer,
  80.  *     done_fetch  out    integer,
  81.  *     emp_name    out    char_array,
  82.  *     job         out    char_array,
  83.  *     sal         out    num_array) is
  84.  *     
  85.  *    begin
  86.  *      if NOT get_emp%ISOPEN then     -- open the cursor if it is
  87.  *        open get_emp(dept_number);   -- not already open
  88.  *      end if;
  89.  * 
  90.  * -- Fetch up to "batch_size" rows into PL/SQL table,
  91.  * -- tallying rows found as they are retrieved.  When end
  92.  * -- of fetch is encountered, close the cursor and exit
  93.  * -- the loop, returning only the last set of rows found.
  94.  * 
  95.  *     done_fetch := FALSE;
  96.  *     found := 0;
  97.  * 
  98.  *     for i in 1..batch_size loop
  99.  *        fetch get_emp               -- get one emp table row
  100.  *          into emp_name(i), job(i), sal(i);
  101.  * 
  102.  *        if get_emp%notfound then    -- if no row was found, then
  103.  *          close get_emp;            -- close the cursor
  104.  *          done_fetch := TRUE;       -- indicate all done
  105.  *          exit;                     -- exit the loop
  106.  *        else
  107.  *          found := found + 1;       -- else count the row and continue
  108.  *          end if;
  109.  *     end loop;
  110.  *    end;
  111.  * end;
  112.  * /
  113.  */
  114.  
  115. #include <stdio.h>
  116. #include <stdlib.h>
  117. #include <string.h>
  118.  
  119. #include <oratypes.h>
  120. #include <ocidfn.h>
  121. #ifdef __STDC__
  122. #include <ociapr.h>
  123. #else
  124. #include <ocikpr.h>
  125. #endif
  126. #include <ocidem.h>
  127.  
  128. #define MAX_ARRAY_SIZE     5
  129. #define NO_PARSE_DEFER     0
  130. #define V7_LNGFLG          2
  131. #define VC_LENGTH         20
  132.  
  133. /* Declare the data areas. */
  134. Cda_Def cda;
  135. Lda_Def lda;
  136. ub1     hda[256];
  137.  
  138. /*  Declare routines in this program */
  139. dvoid do_fetch(/*_ void _*/);
  140. dvoid oci_error(/*_ void _*/);
  141.  
  142. void main(argc, argv)
  143. sword argc;
  144. text **argv;
  145. {
  146.     text username[128];
  147.  
  148.     if (argc > 1)
  149.         strncpy((char *) username, (char *) argv[1],
  150.                 sizeof (username) - 1);
  151.     else
  152.         strcpy((char *) username, "SCOTT/TIGER");
  153.  
  154.     if (orlon(&lda, hda, username, -1, (text *) 0, -1, -1))
  155.     {
  156.         printf("Cannot connect as %s. Exiting...\n", username);
  157.         exit(-1);
  158.     }
  159.     else
  160.         printf("Connected.\n");
  161.  
  162.     /* Open the OCI cursor. */
  163.     if (oopen(&cda, &lda, (text *) 0, -1, -1, (text *) 0, -1))
  164.     {
  165.         printf("Cannot open cursor data area, exiting...\n");
  166.         exit(-1);
  167.     }
  168.  
  169.     /* Fetch and print the data. */
  170.     do_fetch();
  171.  
  172.     /* Close the OCI cursor. */
  173.     if (oclose(&cda))
  174.     {
  175.         printf("Error closing cursor!\n");
  176.         exit(-1);
  177.     }
  178.  
  179.     /* Disconnect from ORACLE. */
  180.     if (ologof(&lda))
  181.     {
  182.         printf("Error logging off!\n");
  183.         exit(-1);
  184.     }
  185.     exit(0);
  186. }
  187.  
  188.  
  189. /*  Set up an anonymous PL/SQL call to the stored
  190.     procedure that fetches the data. */
  191. dvoid
  192. do_fetch(/*_ void _*/)
  193. {
  194.     text *call_fetch = (text *) "\
  195.       begin\
  196.         calldemo.get_employees(:deptno, :t_size, :num_ret, :all_done,\
  197.                              :e_name, :job, :sal);\
  198.       end;";
  199.     sword table_size = MAX_ARRAY_SIZE;
  200.     sword i, n_ret, done_flag;
  201.     sword dept_num;
  202.     sb2 n_ret_indp;
  203.     ub2 n_ret_len, n_ret_rcode;
  204.     ub4 n_ret_cursiz = 0;
  205.  
  206.     text emp_name[MAX_ARRAY_SIZE][VC_LENGTH];
  207.     sb2 emp_name_indp[MAX_ARRAY_SIZE];
  208.     ub2 emp_name_len[MAX_ARRAY_SIZE];
  209.     ub2 emp_name_rcode[MAX_ARRAY_SIZE];
  210.     ub4 emp_name_cursiz = (ub4) MAX_ARRAY_SIZE;
  211.  
  212.     text job[MAX_ARRAY_SIZE][VC_LENGTH];
  213.     sb2 job_indp[MAX_ARRAY_SIZE];
  214.     ub2 job_len[MAX_ARRAY_SIZE];
  215.     ub2 job_rcode[MAX_ARRAY_SIZE];
  216.     ub4 job_cursiz = (ub4) MAX_ARRAY_SIZE;
  217.  
  218.     float salary[MAX_ARRAY_SIZE];
  219.     sb2 salary_indp[MAX_ARRAY_SIZE];
  220.     ub2 salary_len[MAX_ARRAY_SIZE];
  221.     ub2 salary_rcode[MAX_ARRAY_SIZE];
  222.     ub4 salary_cursiz = (ub4) MAX_ARRAY_SIZE;
  223.  
  224.     /* parse the anonymous SQL block */
  225.     if (oparse(&cda, call_fetch, -1,
  226.                NO_PARSE_DEFER, V7_LNGFLG))
  227.     {
  228.         oci_error();
  229.         return;
  230.     }
  231.  
  232.     /* initialize the bind arrays */
  233.     for (i = 0; i < MAX_ARRAY_SIZE; i++)
  234.     {
  235.         emp_name[i][0] = '\0';
  236.         emp_name_len[i] = VC_LENGTH;
  237.         job[i][0]= '\0';
  238.         job_len[i] = VC_LENGTH;
  239.         salary[i] = (float)0;
  240.         salary_len[i] = sizeof (float);
  241.     }
  242.  
  243.     n_ret_len = sizeof (sword);
  244.  
  245.     /* bind the department number IN parameter */
  246.     if (obndrv(&cda, (text *) ":deptno", -1, (ub1 *) &dept_num,
  247.                (sword) sizeof (sword), INT_TYPE, -1,
  248.                (sb2 *) 0, (text *) 0, -1, -1))
  249.     {
  250.         oci_error();
  251.         return;
  252.     }
  253.     /* bind the table size IN parameter */
  254.     if (obndrv(&cda, (text *) ":t_size", -1, (ub1 *) &table_size,
  255.                (sword) sizeof (sword),
  256.                INT_TYPE, -1, (sb2 *) 0, (text *) 0, -1, -1))
  257.     {
  258.         oci_error();
  259.         return;
  260.     }
  261.     /* bind the fetch done OUT parameter */
  262.     if (obndrv(&cda, (text *) ":all_done", -1, (ub1 *) &done_flag,
  263.                (sword) sizeof (sword),
  264.                INT_TYPE, -1, (sb2 *) 0, (text *) 0, -1, -1))
  265.     {
  266.         oci_error();
  267.         return;
  268.     }
  269.  
  270.     /* Bind the OUT n_ret using obndra. obndrv could
  271.        have been used just as well, since no arrays
  272.        are involved, but it is possible to use obndra
  273.        for scalars as well. */
  274.     if (obndra(&cda,
  275.            (text *) ":num_ret",
  276.            -1,
  277.            (ub1 *) &n_ret,
  278.            (sword) sizeof (sword),
  279.            INT_TYPE,
  280.            -1,
  281.            &n_ret_indp,
  282.            &n_ret_len,
  283.            &n_ret_rcode,
  284.            (ub4) 0,      /* pass as 0, not 1, when binding a scalar */
  285.            (ub4 *) 0,    /* pass as the null pointer when scalar */
  286.            (text *) 0,
  287.            -1,
  288.            -1))
  289.     {
  290.         oci_error();
  291.         return;
  292.     }
  293.     
  294.     /* bind the employee name array */
  295.     if (obndra(&cda,
  296.            (text *) ":e_name",
  297.            -1,
  298.            (ub1 *) emp_name,
  299.            VC_LENGTH,
  300.            VARCHAR2_TYPE,
  301.            -1,
  302.            emp_name_indp,
  303.            emp_name_len,
  304.            emp_name_rcode,
  305.            (ub4) MAX_ARRAY_SIZE,
  306.            &emp_name_cursiz,
  307.            (text *) 0,
  308.            -1,
  309.            -1))
  310.     {
  311.         oci_error();
  312.         printf("error happened after emplyee");
  313.         return;
  314.     }
  315.  
  316.     /* bind the job array */
  317.     if (obndra(&cda,
  318.            (text *) ":job",
  319.            -1,
  320.            (ub1 *) job,
  321.            VC_LENGTH,
  322.            VARCHAR2_TYPE,
  323.            -1,
  324.            job_indp,
  325.            job_len,
  326.            job_rcode,
  327.            (ub4) MAX_ARRAY_SIZE,
  328.            &job_cursiz,
  329.            (text *) 0,
  330.            -1,
  331.            -1))
  332.     {
  333.         oci_error();
  334.         printf("error happened after job");    
  335.         return;
  336.     }
  337.  
  338.     /* bind the salary array */
  339.     if (obndra(&cda,
  340.            (text *) ":sal",
  341.            -1,
  342.            (ub1 *) salary,
  343.            (sword) sizeof (float),
  344.            FLOAT_TYPE,
  345.            -1,
  346.            salary_indp,
  347.            salary_len,
  348.            salary_rcode,
  349.            (ub4) MAX_ARRAY_SIZE,
  350.            &salary_cursiz,
  351.            (text *) 0,
  352.            -1,
  353.            -1))
  354.     {
  355.         oci_error();
  356.         return;
  357.     }
  358.  
  359.     printf("\nenter deptno: ");
  360.     scanf("%d", &dept_num);
  361.  
  362.     for (;;)
  363.     {
  364.         /* execute the fetch */
  365.         if (oexec(&cda))
  366.         {
  367.             oci_error();
  368.             return;
  369.         }
  370.  
  371.         printf("\n%d row%c returned\n",
  372.                n_ret, n_ret == 1 ? '\0' : 's');
  373.  
  374.         if (n_ret > 0)
  375.         {
  376.             printf("\n%-*.*s%-*.*s%s\n",
  377.                    VC_LENGTH, VC_LENGTH, "Employee Name",
  378.                    VC_LENGTH, VC_LENGTH, "Job", "   Salary");
  379.             for (i = 0; i < n_ret; i++)
  380.             {
  381.                 printf("%.*s", emp_name_len[i], emp_name[i]);
  382.                 printf("%*c", VC_LENGTH - emp_name_len[i], ' ');
  383.                 printf("%.*s", job_len[i], job[i]);
  384.                 printf("%*c", VC_LENGTH - job_len[i], ' ');
  385.                 printf("%8.2f\n", salary[i]);
  386.             }
  387.         }
  388.         if (done_flag != 0)
  389.         {
  390.             printf("\n");
  391.             break;
  392.         }
  393.     }
  394.     return;
  395. }
  396.  
  397.  
  398. dvoid
  399. oci_error(/*_ void _*/)
  400. {
  401.     text msg[900];
  402.     sword rv;
  403.  
  404.     rv = oerhms(&lda, cda.rc, msg, (sword) sizeof (msg));
  405.  
  406.     printf("\n\n%.*s", rv, msg);
  407.     printf("Processing OCI function %s\n",
  408.            oci_func_tab[(int) cda.fc]);
  409.     return;
  410. }
  411.  
  412.  
  413.